package com.yonyou.pmclouds.organization.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.SqlUtil;
import com.yonyou.pmclouds.organization.entity.OrgAndRoleVO;
import com.yonyou.pmclouds.organization.entity.OrgConst;
import com.yonyou.pmclouds.organization.entity.OrganizationVO;
import com.yonyou.pmclouds.organization.mapper.OrgAndRoleMapper;
import com.yonyou.pmclouds.organization.mapper.OrganizationMapper;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationQuery;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = OrganizationQuery.class)
public class OrganizationQueryImpl implements OrganizationQuery {
    @Autowired
    private OrganizationMapper mapper;

    @Autowired
    private OrgAndRoleMapper roleMapper;

    @Override
    public OrganizationVO[] queryOrgList(String pkTenant, String pkRole) {
        if (StringUtils.isEmpty(pkTenant) || StringUtils.isEmpty(pkRole)) return new OrganizationVO[0];

        OrganizationVO[] organizationVOS = mapper.getOrgByTenant(pkTenant, OrgConst.ENABLE_STATE, null);
        OrgAndRoleVO[] orgAndRoleVOS = roleMapper.getOrgByRole(pkTenant, SqlUtil.getSqlIn(new String[]{pkRole}));
        if (ArrayUtils.isEmpty(organizationVOS)) {
            return new OrganizationVO[0];
        }
        Set<String> recordRoleOrg = new HashSet<>();
        if (ArrayUtils.isNotEmpty(orgAndRoleVOS)) {
            for (OrgAndRoleVO vo : orgAndRoleVOS) {
                if (vo != null && StringUtils.isNotEmpty(vo.getPkOrganization())) {
                    recordRoleOrg.add(vo.getPkOrganization());
                }
            }
        }
        for (OrganizationVO vo : organizationVOS) {
            if (vo != null && StringUtils.isNotEmpty(vo.getPkOrganization()) && recordRoleOrg.contains(vo.getPkOrganization())) {
                vo.setIsDistributed(true);
            }
        }
        return getOrgTree(organizationVOS);
    }

    @Override
    public OrganizationVO queryByPkSrc(String pkTenant, String pkSrc) throws BusinessException {
        //利用租户主键以及组织主键数组批量查询组织。
        OrganizationVO[] result = mapper.queryByPkSrcs(pkTenant, SqlUtil.getSqlIn(new String[]{pkSrc}));
        if (ArrayUtils.isEmpty(result)) return null;
        return result[0];
    }


    //构造组织树形结构，返回根节点数组
    private OrganizationVO[] getOrgTree(OrganizationVO[] organizationVOS) {

        if (ArrayUtils.isEmpty(organizationVOS)) {
            return new OrganizationVO[0];
        }
        //构造树
        Map<String, List<OrganizationVO>> orgChildMap = new HashMap<>();
        for (OrganizationVO vo : organizationVOS) {
            String parent = vo.getPkParent();
            if (StringUtils.isEmpty(parent)) {
                parent = StringUtils.EMPTY;
            }
            List<OrganizationVO> children = orgChildMap.get(parent);
            if (children == null) {
                children = new ArrayList<>();
                orgChildMap.put(parent, children);
            }
            children.add(vo);
        }
        // 这里可能不是一颗完整的数，所以将父节点存在于vos中的删除，剩下的就是需要直接挂到根节点了
        for (OrganizationVO vo : organizationVOS) {
            List<OrganizationVO> children = orgChildMap.get(vo.getPkSrc());  //父组织存的是NC的主键pkSrc
            if (children != null) {
                vo.setChildren(children.toArray(new OrganizationVO[0]));
            }
            orgChildMap.remove(vo.getPkSrc());
        }
        List<OrganizationVO> result = orgChildMap.get(StringUtils.EMPTY);
        if (result == null) {
            result = new ArrayList<>();
        }
        orgChildMap.remove(StringUtils.EMPTY);
        for (List<OrganizationVO> orgs : orgChildMap.values()) {
            result.addAll(orgs);
        }
        Collections.sort(result, new Comparator<OrganizationVO>() {
            @Override
            public int compare(OrganizationVO o1, OrganizationVO o2) {
                if (o1 == null && o2 == null) {
                    return 0;
                }
                if (o1 == null) {
                    return 1;
                }
                if (o2 == null) {
                    return -1;
                }
                return ChineseStringUtils.compareInDict(o1.getScode(), o2.getScode());
            }
        });
        return result.toArray(new OrganizationVO[0]);
    }

    @Override
    public OrganizationVO[] queryOrgListByTenantId(String pkTenant) throws BusinessException {

        return this.queryOrgListByTenantWithKeyword(pkTenant, null);
    }

    @Override
    public OrganizationVO[] queryOrgListByTenantWithKeyword(String pkTenant, String keyword) {
        if (StringUtils.isEmpty(pkTenant)) {
            pkTenant = RuntimeEnvironment.getTenantId();
        }
        if (StringUtils.isEmpty(pkTenant)) {
            return new OrganizationVO[0];
        }
        OrganizationVO[] organizationVOS = mapper.getOrgByTenant(pkTenant, OrgConst.ENABLE_STATE, keyword);
        if (ArrayUtils.isEmpty(organizationVOS)) {
            return new OrganizationVO[0];
        }
        return getOrgTree(organizationVOS);
    }

    @Override
    public OrganizationVO[] queryByPkSrcs(String pkTenant, String[] pkSrcs) throws BusinessException {
        if (StringUtils.isEmpty(pkTenant) || ArrayUtils.isEmpty(pkSrcs)) return new OrganizationVO[0];
        return mapper.queryByPkSrcs(pkTenant, SqlUtil.getSqlIn(pkSrcs));
    }

    @Override
    public OrganizationVO[] queryOrgByRoles(String pkTenant, String[] pkRoles) throws BusinessException {

        if (StringUtils.isEmpty(pkTenant))
            pkTenant = RuntimeEnvironment.getTenantId();

        if (ArrayUtils.isEmpty(pkRoles))
            return new OrganizationVO[0];

        OrgAndRoleVO[] orgAndRoleVOs = roleMapper.getOrgByRole(pkTenant, SqlUtil.getSqlIn(pkRoles));

        Set<String> recordRoleOrg = new HashSet<>();
        if (ArrayUtils.isNotEmpty(orgAndRoleVOs)) {
            for (OrgAndRoleVO vo : orgAndRoleVOs) {
                if (vo != null && StringUtils.isNotEmpty(vo.getPkOrganization())) {
                    recordRoleOrg.add(vo.getPkOrganization());
                }
            }
        }
        if (recordRoleOrg.size() == 0)
            return new OrganizationVO[0];

        OrganizationVO[] organizationVOs = mapper.queryByPkOrgs(pkTenant, SqlUtil.getSqlIn(recordRoleOrg.toArray(new String[0])));

        return getOrgTree(organizationVOs);
    }

    @Override
    public String[] queryOrgIdsByRoles(String pkTenant, String[] pkRoles) throws BusinessException {
        if (StringUtils.isEmpty(pkTenant))
            pkTenant = RuntimeEnvironment.getTenantId();

        if (ArrayUtils.isEmpty(pkRoles))
            return new String[0];

        return roleMapper.queryOrgIdsByRoles(pkTenant, pkRoles);
    }

    @Override
    public OrganizationVO queryById(String id) throws BusinessException {
        return mapper.getById(id);
    }

    @Override
    public OrganizationVO[] queryByIds(String[] ids) throws BusinessException {
        return mapper.queryByIds(ids);
    }

}
